package Underworld_Survival;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.function.Consumer;

//当前战斗时 buff可能触发的时期：攻击后，受伤前，回合结束后

import static Underworld_Survival.Game.*;
import static Underworld_Survival.GameOutput.MsgType;
import static Underworld_Survival.GameOutput.Template.mUseSkill;
import static Underworld_Survival.GameOutput.Template.pUseSkill;

public class BattleManager {
    private Player player;//玩家
    private boolean isPlayerTurn;//确定战前谁先手
    private Role attacker;//发起攻击的人(发起攻击只能是一个人，就是谁的回合)
    private Role target;//被攻击的人
    private int injuryValue=0;//被攻击者的受伤值（用于反弹伤害，处理各种效果）
    private List<Monster> enemy=new ArrayList<>();//这场战斗的敌人列表(战斗初始的所有敌人)
    private List<Monster> livingEnemy = new ArrayList<>();//所有活着的敌人
    private List<EquipmentSpecialEffect> attackerEquipEffects = new ArrayList<>();
    private List<EquipmentSpecialEffect> targetEquipEffects = new ArrayList<>();

    public BattleManager() {}
    public BattleManager(Player player, boolean isPlayerTurn, Role attacker, Role target, int injuryValue, List<Monster> enemy, List<Monster> livingEnemy) {
        this.player = player;
        this.isPlayerTurn = isPlayerTurn;
        this.attacker = attacker;
        this.target = target;
        this.injuryValue = injuryValue;
        this.enemy = enemy;
        this.livingEnemy = livingEnemy;
    }
    public BattleManager(Player player,List<Monster> enemy) {
        this.player=player;
        this.enemy=enemy;
        livingEnemy=enemy;
    }

    public void startBattle() {
        gameOutput.println(MsgType.BATTLE,"⚔\uFE0F⚔\uFE0F⚔\uFE0F============ 战斗开始！============⚔\uFE0F⚔\uFE0F⚔\uFE0F");
        int round=1;

        //战斗开始前

        while (player.isAlive() && hasLivingEnemy()) {
        //战斗中
            initBattle(player,livingEnemy.get(0));
            gameOutput.println(MsgType.BATTLE,"⏳第---"+round+"---轮双方交战！");
            if(player.getTotalEP()>enemy.get(0).getTotalEP()){setIsPlayerTurn(true);}
            else{setIsPlayerTurn(false);}
            //player特殊装备或者能力触发
            triggerEquipEffects(attackerEquipEffects, eff -> eff.beforeBattle(this));
            if(isPlayerTurn){
                playerTurn();
                if (!hasLivingEnemy()) break;
                enemyTurn(round);
                round++;
            }else{
                if (!hasLivingEnemy()) break;
                enemyTurn(round);
                if (!hasLivingEnemy()) break;//确保玩家回合开始时有活着的敌人
                playerTurn();
                round++;
            }

        }
        //战斗结束后
        endBattle();
    }

    private void playerTurn() {
        attacker=player;
        target=null;//置空被攻击者，选择技能后在添回来
        gameOutput.println(MsgType.BATTLE,"=== 你的回合 ===");
        //回合开始

        while(true) {
            for(int i=0;i<livingEnemy.size();i++){
                GameOutput.ShowMonster.currentHP(livingEnemy.get(i));//展示所有敌人及其血量
            }
            System.out.println();
            GameOutput.ShowPlayer.battleStatus();//展示生命值,buff和技能
            gameOutput.println(MsgType.GET,player.ability.getActiveSkill().size()+
                    ".\uD83C\uDF56补充食物" + '\t' + "效果：恢复血量和能量，失去一次攻击的机会");
            gameOutput.println(MsgType.SYSTEM,"请选择你要进行的操作：");
            int select = inputCheck(1, player.ability.getActiveSkill().size());
            //玩家操作，决定攻击或者补充状态
            if (select == player.ability.getActiveSkill().size()) {//补充食物
                gameOutput.println(MsgType.SYSTEM,"请选择你要使用的食物：");
                List<Food> distinctNameList = player.bag.showFoodVertically();
                if (!distinctNameList.isEmpty()) {
                    gameOutput.println(MsgType.BAG,(distinctNameList.size() + 1) + ".取消使用");
                    int select2 = inputCheck(1, distinctNameList.size() + 1);
                    if (select2 != distinctNameList.size() + 1) {
                        player.useSupply(distinctNameList.get(select2 - 1));
                        //回合结束
                        break;
                    }
                }
            } else {//使用技能
                Skill selectedSkill=player.ability.getActiveSkill().get(select);
                if (!player.canUseSkill(selectedSkill) ){//能量不足，无法使用技能
                    target=livingEnemy.get(0);
                    initBattle(attacker,target);
                    player.ability.getActiveSkill().get(0).applyEffect(this);
                    //攻击后
                    triggerEquipEffects(attackerEquipEffects, eff -> eff.onAttackStart(this));
                    player.triggerBuffsInBattle(BuffTriggerCondition.ATTACK_AFTER,this);
                    //敌人受伤前
                    target.triggerBuffsInBattle(BuffTriggerCondition.INJURED_BEFORE,this);
                    target.reduceHP(injuryValue);
                    break;
                    //回合结束
                }else{
                    player.reduceAgi(selectedSkill.getConsumeAgi());
                    if(livingEnemy.size()==1||!selectedSkill.isIsSingleTarget()){//只有一个敌人，或者技能是群攻技能
                        gameOutput.println(MsgType.BATTLE,"你使用技能："+selectedSkill.getSkillName());
                        for(int i=0;i<livingEnemy.size();i++){
                            target=livingEnemy.get(i);
                            initBattle(attacker,target);
                            selectedSkill.applyEffect(this);//使用技能
                            gameOutput.println(MsgType.BATTLE,"对"+target.getName()+"造成："+injuryValue+"点伤害");
                            pressAnyKeyToContinue();

                            //攻击后
                            triggerEquipEffects(attackerEquipEffects, eff -> eff.onAttackStart(this));
                            player.triggerBuffsInBattle(BuffTriggerCondition.ATTACK_AFTER,this);

                            //敌人受伤前
                            target.triggerBuffsInBattle(BuffTriggerCondition.INJURED_BEFORE,this);
                            target.reduceHP(injuryValue);
                        }
                        //回合结束
                        break;
                    }else{//单体技能，并且有多个敌人
                        target=selectMonster();
                        initBattle(attacker,target);
                        selectedSkill.applyEffect(this);
                        gameOutput.println(MsgType.BATTLE,pUseSkill,selectedSkill.getSkillName(),injuryValue);
                        //"你使用技能：,,,,造成伤害：，，

                        //攻击后
                        triggerEquipEffects(attackerEquipEffects, eff -> eff.onAttackStart(this));
                        player.triggerBuffsInBattle(BuffTriggerCondition.ATTACK_AFTER,this);

                        //敌人受伤前
                        target.triggerBuffsInBattle(BuffTriggerCondition.INJURED_BEFORE,this);
                        target.reduceHP(injuryValue);
                        break;
                    }
                }
            }
        }
        //回合结束
        injuryValue=0;
        updateLivingEnemy();
        player.triggerBuffsInBattle(BuffTriggerCondition.TURN_END,this);
    }

    private void enemyTurn(int round) {
        this.target=player;
        gameOutput.println(MsgType.BATTLE,"=== 敌方回合 ===");
        if(livingEnemy.isEmpty()){
            throw new IllegalStateException("战斗异常，未能成功获取敌人列表！");
        }
        List<Monster> copyOfLivingEnemy = new ArrayList<>(livingEnemy);
        for(Monster monster: copyOfLivingEnemy){//获取所有活着的敌人
            if(monster==null) continue;
            if (!monster.isAlive()) continue;
            if(monster.ability.getActiveSkill().isEmpty()){
                throw new IllegalStateException("敌人没有主动技能！");
            }
            attacker=monster;
            initBattle(attacker,target);
            monster.showBuff();
            Skill skill=monster.ability.getActiveSkill().get(round%monster.getSkillCount());
            skill.applyEffect(this);
            gameOutput.println(MsgType.BATTLE,mUseSkill,monster.getName(),skill.getSkillName(),injuryValue);
            //。。。使用技能。。。，造成伤害：。。。

            //攻击后
            monster.triggerBuffsInBattle(BuffTriggerCondition.ATTACK_AFTER,this);

            //玩家受伤前
            player.triggerBuffsInBattle(BuffTriggerCondition.INJURED_BEFORE,this);
            player.reduceHP(injuryValue);

            //玩家受伤后
            triggerEquipEffects(targetEquipEffects, eff -> eff.afterInjured(this));

            //回合结束
            monster.triggerBuffsInBattle(BuffTriggerCondition.TURN_END,this);
            injuryValue=0;
            pressAnyKeyToContinue();
        }
        updateLivingEnemy();
    }

    private void endBattle() {
        gameOutput.println(MsgType.BATTLE,"\n====== 战斗结束 ======");
        if (player.isAlive()) {
            gameOutput.println(MsgType.BATTLE,"胜利！");
        } else {
            gameOutput.println(MsgType.DIE,"你被击败了...");
        }
    }

    //单体技能，选择一个目标
    public Monster selectMonster(){
        gameOutput.println(MsgType.SYSTEM,"请选择你要攻击的敌人：");
        for(int i=0;i<livingEnemy.size();i++){
            System.out.printf((i+1)+".");
            GameOutput.ShowMonster.currentHP(livingEnemy.get(i));
        }
        System.out.println();
        int select=inputCheck(1,livingEnemy.size());
        return livingEnemy.get(select-1);
    }
    //更新活着的敌人
    public void updateLivingEnemy(){
        Iterator<Monster> iterator=livingEnemy.iterator();
        while(iterator.hasNext()){
            Monster monster=iterator.next();
            if(monster.getCurrentHP()==0){
                gameOutput.print(MsgType.DIE,monster.getName()+"死亡！ ");
                iterator.remove();
            }
        }
        System.out.println();
    }
    // 初始化战斗时收集双方装备效果
    public void initBattle(Role attacker, Role target) {
        attackerEquipEffects.clear();
        targetEquipEffects.clear();
        this.attacker = attacker;
        this.target = target;
        // 收集攻击方装备效果
        attacker.getEquipments().forEach(eq ->
                attackerEquipEffects.addAll(eq.getSpecialEffect()));
        // 收集防御方装备效果
        target.getEquipments().forEach(eq ->
                targetEquipEffects.addAll(eq.getSpecialEffect()));
    }
    // 通用效果触发方法
    private void triggerEquipEffects(List<EquipmentSpecialEffect> effects,
                                Consumer<EquipmentSpecialEffect> action) {
        effects.forEach(action::accept);
    }


    //getter,setter
    private boolean hasLivingEnemy() {return livingEnemy.stream().anyMatch(Monster::isAlive);}
    public Player getPlayer() {return player;}
    public void setPlayer(Player player) {this.player = player;}
    public boolean isIsPlayerTurn() {return isPlayerTurn;}
    public void setIsPlayerTurn(boolean isPlayerTurn) {this.isPlayerTurn = isPlayerTurn;}
    public Role getAttacker() {return attacker;}
    public void setAttacker(Role attacker) {this.attacker = attacker;}
    public Role getTarget() {return target;}
    public void setTarget(Role target) {this.target = target;}
    public int getInjuryValue() {return injuryValue;}
    public void setInjuryValue(int injuryValue) {this.injuryValue = injuryValue;}
    public List<Monster> getEnemy() {return enemy;}
    public void setEnemy(List<Monster> enemy) {this.enemy = enemy;}
    public List<Monster> getLivingEnemy() {return livingEnemy;}
    public void setLivingEnemy(List<Monster> livingEnemy) {this.livingEnemy = livingEnemy;}

}
